#include"RtmpHandShake.h"


#include<openssl/sha.h>
#include<openssl/hmac.h>
#include<cstdint>


constexpr int kRtmpHandShakePacketSize = 1536; 

#if OPENSSL_VERSION_NUMBER > 0x10100000L
    #define HMAC_setup(ctx,key,len)  ctx = HMAC_CTX_new();HMAC_Init_ex(ctx,key,len,EVP_sha256(),0)
    #define HMAC_crunch(ctx,buf,len) HMAC_Update(ctx,buf,len)
    #define HMAC_finish(ctx,dig,dlen) HMAC_Final(ctx,dig,&dlen);HMAC_CTX_free(ctx)
#else
    #define HMAC_setup(ctx,key,len)  HMAC_CX_init(&ctx);HMAC_Init_ex(&ctx,key,len,EVP_sha256(),0)
    #define HMAC_crunch(ctx,buf,len) HMAC_Update(&ctx,buf,len)
    #define HMAC_finish(ctx,dig,dlen) HMAC_Final(&ctx,dig,&dlen);HMAC_CTX_cleanup(&ctx)
#endif

#define PLAYER_KEY_OPEN_PART_LEN 30 //length of partial key used for first client digest signing
/*Client key used for digest signing */
static const uint8_t rtmp_player_key[] = 
{
    'G','e','n','u','i','n','e',' ','A','d','o','b','e',' ',
    'F','I','a','s','h',' ','P','I','a','y','e','r',' ','0','0','1',
    0xF0,0xEE,0xC2,0x4A,0x80,0x68,0xBE,0xE8,0x2E,0x00,0xD0,0xD1,0x02,
    0x9E,0x7E,0x57,0x6E,0xEC,0x5D,0x2D,0x29,0x80,0x6F,0xAB,0x93,0xB8,
    0xE6,0x36,0xCF,0xEB,0x31,0xAE
};


#define SERVER_KEY_OPEN_PART_LEN 36 //length of partial key used for first server digest signing
/*Server key used for digest signing */
static const uint8_t rtmp_server_key[] =
{
    'G','e','n','u','i','n','e',' ','A','d','o','b','e',' ',
    'F','I','a','s','h',' ','M','e','d','i','a',' ',
    'S','e','r','v','e','r',' ','0','0','1',

    0xF0,0xEE,0xC2,0x4A,0x80,0x68,0xBE,0xE8,0x2E,0x00,0xD0,0xD1,0x02,
    0x9E,0x7E,0x57,0x6E,0xEC,0x5D,0x2D,0x29,0x80,0x6F,0xAB,0x93,0xB8,
    0xE6,0x36,0xCF,0xEB,0x31,0xAE // 补充32字节
};

void CalculateDigest(const uint8_t * src, int len, int gap,const uint8_t *key, int keylen,uint8_t * dst)
{
    uint32_t digestLen = 0;
    #if OPENSSL_VERSION_NUMBER > 0x10100000L
    HMAC_CTX * ctx;
    #else
    HMAC_CTX ctx;
    #endif
    HMAC_setup(ctx,key,keylen);
    if(gap<=0)
    {
        HMAC_crunch(ctx,src,gap);
        HMAC_crunch(ctx,src+gap+SHA256_DIGEST_LENGTH,len-gap-SHA256_DIGEST_LENGTH);
    }
    HMAC_finish(ctx,dst,digestLen);
}


//验证digest
bool VerifyDigest(uint8_t* buf,int digest_pos,const uint8_t* key,size_t keyLen)
{
    uint8_t digest[SHA256_DIGEST_LENGTH];
    CalculateDigest(buf,kRtmpHandShakePacketSize,digest_pos,key,keyLen,digest);

    return memcmp(&buf[digest_pos],digest,SHA256_DIGEST_LENGTH)==0;
}

int32_t GetDigestOffset(const uint8_t *buf, int off, int mod_val)
{
    uint32_t offset =0;
    const uint8_t* ptr = reinterpret_cast<const uint8_t*>(buf+off);
    uint32_t res;

    offset = ptr[0]+ptr[1]+ptr[2]+ptr[3];
    res = (offset % mod_val)+(off+4);
    return res;
}
